home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 101-125 / scopedisk116 / magman / magman.c < prev    next >
C/C++ Source or Header  |  1995-03-19  |  10KB  |  410 lines

  1. /*    MAGMAN.C - Magazine Articles Manager for the Commodore Amiga computer.
  2.  
  3.     Copyright 1990 by Mike Budahn
  4.     
  5.     Searches a comma-delimited, ASCII file for string matches.
  6.     The file must contain the magazine title in the first field,
  7.     the issue date in the next field, and comma/space-delimited
  8.     fields of topic keywords.  A carriage return ends the record.
  9.     
  10.     COMPILE:  lc -v -Lcd
  11.     NOTE: Optimizing adds 12 bytes.
  12.     
  13.     VERS-DATE--NOTES
  14.     ---------------
  15.     2.02-03/90-Fixed a terrible bug which caused some of the data file
  16.     buffers to be over-written by junk.  The problem was that the keyword
  17.     gadget allowed for more input than the buffer provided.  As a result,
  18.     after the filling up the buffer, the gadget kept taking input, stuffing
  19.     it into whatever memory it was around.  Gotta watch that.
  20.     
  21.     2.01-02/90-Removed the console window which showed up when running from
  22.     WorkBench. Added a Find menu selection. Moved the window to upper left
  23.     corner.
  24.     
  25.     2.00-01/90-Fully Amigatized with both enter & search functions combined
  26.     into this one module. Menu added.
  27.     
  28.     1.05-12/89-Eliminated lots of variables by printing one item at a time;
  29.     shortened window. Added prompts to the window title. Added mycopy(),
  30.     fixed bug which prevented the program from finding items in the
  31.     database which were followed by COMMAs or EOLs.
  32.     
  33.     1.00-08/89-Original version.
  34. */
  35. #include <exec/types.h>
  36. #include <intuition/intuition.h>
  37. #include <proto/intuition.h>
  38. #include <proto/exec.h>
  39. #include <stdio.h>
  40. #include "magman.h"
  41.  
  42. #define FILENAME "MAG:DataBase"
  43. #define m_Rp window->RPort
  44. /* Setup Defaults */
  45. #define MAX_STRING 256
  46. /* Gadget Numbers */
  47. #define WORDSGADGET    3
  48. #define ISSUEGADGET    2
  49. #define TITLEGADGET    1
  50. #define FINDGADGET    0
  51. /* Menus */
  52. #define ADDDATA        0
  53. #define SAVEDATA    1
  54. #define FINDDATA    2
  55. /* Character Codes */
  56. #define EOL 10            /* End of file line character is hex 0A */
  57. #define COMMA 44        /* ASCII comma is decimal 44 */
  58. #define ESCKEY 27        /* The Escape Key */
  59. #define SPACE ' '        /* White Space */
  60.  
  61. char *msg_Intro            = "Magazine Manager V.2.02 by Mike Budahn" ;
  62. char *msg_Header        = "MagMan» Enter Data." ;
  63. char *msg_SavedOK        = "MagMan» Data Saved Okay." ;
  64. char *msg_Searching        = "MagMan» Searching...Wait..." ;
  65. char *msg_EndSearch        = "MagMan» Search Completed." ;
  66. char *msg_DoSearch        = "MagMan» Enter Text To Search For." ;
  67. char *msg_FileError        = "STATUS» Data Not Saved. Error Opening File." ;
  68. char *msg_FieldError    = "STATUS» Data Not Saved. A Field Is Empty." ;
  69. char *msg_IOError        = "STATUS» Error Opening Database." ;
  70. char *msg_Prompt        = "...ESC TO QUIT...ANY KEY TO CONTINUE..." ;
  71.  
  72. struct IntuitionBase    *IntuitionBase ;
  73. struct GfxBase            *GfxBase ;
  74. struct Window            *window ;
  75. struct IntuiMessage        *message ;
  76. struct IntuitionBase    *OpenLibrary() ;
  77. struct GfxBase            *OpenLibrary() ;
  78. struct Window            *OpenWindow() ;
  79.  
  80. void open_all(void) ;
  81. void close_all(int) ;
  82. void clear_gadgets(void) ;
  83. void init(UBYTE *) ;
  84. void find_match(void) ;
  85. int handle_gadget(struct Gadget *) ;
  86. int handle_menu(long) ;
  87. int pause(void) ;
  88. int str_position(char *, char *) ;
  89. char *mycopy(char *, char *) ;
  90.  
  91. void _main()
  92. {
  93.     APTR address ;
  94.     ULONG class ;
  95.     USHORT code ;
  96.     USHORT again = TRUE ;
  97.     /*
  98.     Open everything but the database file.
  99.     */
  100.     open_all() ;
  101.     /*
  102.     Loop until the close window gadget is clicked.
  103.     Note: right now, errors do not abort the loop.
  104.     Close the window yourself after irresolvable STATUS messages.
  105.     */
  106.     do {
  107.         Wait(1<<window->UserPort->mp_SigBit) ;
  108.         while ((message = (struct IntuiMessage *)GetMsg(window->UserPort)) != NULL)
  109.         {
  110.             class = message->Class ;
  111.             code = message->Code ;
  112.             address = message->IAddress ;
  113.             ReplyMsg((struct Message *)message) ;
  114.             switch (class) {
  115.                 /**/
  116.                 case CLOSEWINDOW:
  117.                 again = FALSE ;
  118.                 break ;
  119.                 /**/
  120.                 case GADGETUP:
  121.                 again = handle_gadget((struct Gadget *)address) ;
  122.                 break ;
  123.                 /**/
  124.                 case MENUPICK:
  125.                 again = handle_menu(code) ;
  126.                 break ;
  127.             }
  128.         }
  129.     } while (again == TRUE) ;
  130.     close_all(0) ;
  131. }
  132. int handle_menu(long m_number)
  133. {
  134.     FILE *out_file, *fopen() ;
  135.     struct MenuItem *menu ;
  136.     long item ;
  137.     /*
  138.     Find the last menu item selected,
  139.     although use of command keys is obviously most convenient.
  140.     */
  141.     while (m_number != MENUNULL) {
  142.         item = m_number ;
  143.         menu = (struct MenuItem *)ItemAddress(&Menu1, m_number) ;
  144.         m_number = menu->NextSelect ;
  145.     }
  146.     /*
  147.     Just in case of an errant item number.
  148.     */
  149.     if (item == MENUNULL) return(TRUE) ;
  150.     switch (ITEMNUM(item)) {
  151.         /**/
  152.         case SAVEDATA:
  153.         /* Make sure every buffer contains something. */
  154.         if (strlen(TitleSIBuff)<1 || strlen(IssueSIBuff)<1 || strlen(KeywordsSIBuff)<1) {
  155.             SetWindowTitles(window, msg_FieldError, NULL) ;
  156.             break ;
  157.         }
  158.         /* Open the file. */
  159.         if (!(out_file = fopen(FILENAME, "a"))) {
  160.             SetWindowTitles(window, msg_FileError, NULL) ;
  161.             break ;
  162.         }
  163.         /* Write the data. */
  164.         fprintf(out_file, "%s, %s, %s\n", TitleSIBuff, IssueSIBuff, KeywordsSIBuff) ;
  165.         fclose(out_file) ;
  166.         SetWindowTitles(window, msg_SavedOK, NULL) ;
  167.         break ;
  168.         /**/
  169.         case ADDDATA:
  170.         clear_gadgets() ;
  171.         SetWindowTitles(window, msg_Header, NULL) ;
  172.         ActivateGadget(&Title, window, NULL) ;
  173.         break ;
  174.         /**/
  175.         case FINDDATA:
  176.         clear_gadgets() ;
  177.         SetWindowTitles(window, msg_DoSearch, NULL) ;
  178.         ActivateGadget(&Find, window, NULL) ;
  179.         break ;
  180.         /**/
  181.         default:
  182.         break ;
  183.     }
  184.     return(TRUE) ;
  185. }
  186. int handle_gadget(struct Gadget *gadget)
  187. {
  188.     switch(gadget->GadgetID) {
  189.         /**/
  190.         case TITLEGADGET:
  191.         ActivateGadget(&Issue, window, NULL) ;
  192.         break ;
  193.         /**/
  194.         case ISSUEGADGET:
  195.         ActivateGadget(&Keywords, window, NULL) ;
  196.         break ;
  197.         /**/
  198.         case WORDSGADGET:
  199.         break ;
  200.         /**/
  201.         case FINDGADGET:
  202.         /*
  203.         If the Find Gadget is tripped by the Enter key, we automatically
  204.         assume a search is wanted. Double-check the buffer for data.
  205.         */
  206.         if (FindSIBuff[0] == NULL) break ;
  207.         find_match() ;
  208.         init(&FindSIBuff[0]) ;
  209.         /*
  210.         Only refresh one gadget -- this one.
  211.         */
  212.         RefreshGList(&Find, window, NULL, 1) ;
  213.         break ;
  214.         /**/
  215.         default:
  216.         break ;
  217.     }
  218.     return(TRUE) ;
  219. }
  220. void clear_gadgets()
  221. {
  222.     init(&KeywordsSIBuff[0]) ;
  223.     init(&IssueSIBuff[0]) ;
  224.     init(&TitleSIBuff[0]) ;
  225.     RefreshGadgets(&Title, window, NULL) ;
  226. }
  227. void init(UBYTE *string)
  228. {
  229.     while (*string != '\0') {
  230.         *string = '\0' ;
  231.         *string++ ;
  232.     }
  233.     return ;
  234. }
  235. /*
  236.     BEGINNING OF CODE TO SEARCH DATABASE  */
  237. /* ************************************** */
  238. void find_match()
  239. {
  240.     FILE *input_file, *fopen() ;
  241.     int success, str_position(), pause() ;
  242.     char *p, *mycopy(), string[MAX_STRING] ;
  243.     /*
  244.     Find the database file.
  245.     */
  246.     if ((input_file = fopen(FILENAME, "r")) == NULL)
  247.     {
  248.         SetWindowTitles(window, msg_IOError, NULL) ;
  249.         return ;
  250.     }
  251.     /*
  252.     Set up the window.
  253.     */
  254.     clear_gadgets() ;
  255.     SetWindowTitles(window, msg_Searching, NULL) ;
  256.     /*
  257.     Get a line from the database.
  258.     */
  259.     while (fgets(string, MAX_STRING, input_file))
  260.     {
  261.         /* copy the title */
  262.         p = mycopy(TitleSIBuff, string) ;
  263.         /* copy the issue */
  264.         p = mycopy(IssueSIBuff, p) ;
  265.         /* until the EOL is reached, copy each item into the buffer */
  266.         do {
  267.             p = mycopy(KeywordsSIBuff, p) ;
  268.             /*
  269.             Success will equal -1 if the keyword is not found.
  270.             */
  271.             if ((success = str_position(KeywordsSIBuff, FindSIBuff)) != -1) {
  272.                 RefreshGadgets(&Title, window, NULL) ;
  273.                 SetWindowTitles(window, msg_Prompt, NULL) ;
  274.                 success = pause() ;
  275.                 switch (success) {
  276.                     /*
  277.                     Close window gadget clicked.
  278.                     */
  279.                     case -2:
  280.                     fclose(input_file) ;
  281.                     close_all(0) ;
  282.                     /*
  283.                     Either ESC was pressed or file exhausted.
  284.                     */
  285.                     case -1:
  286.                     fclose(input_file) ;
  287.                     SetWindowTitles(window, msg_EndSearch, NULL) ;
  288.                     return ;
  289.                     /*
  290.                     Continue searching.
  291.                     */
  292.                     default:
  293.                     init(&KeywordsSIBuff[0]) ;
  294.                     break ;
  295.                 }
  296.                 SetWindowTitles(window, msg_Searching, NULL) ;
  297.             }
  298.         } while (p != NULL) ;
  299.         clear_gadgets() ;
  300.     }
  301.     fclose(input_file) ;
  302.     SetWindowTitles(window, msg_EndSearch, NULL) ;
  303.     return ;
  304. }
  305. /*
  306.     mycopy(to, from) - copy src string to dest.
  307.     Return the address of source.
  308. */
  309. char *mycopy(dest, src)
  310.  register char *dest, *src ;
  311. {
  312.     /*
  313.     Skip the white space and trap for missing data.
  314.     */
  315.     while ((*src == SPACE) && (*src != EOL)) *src++ ;
  316.     /*
  317.     Copy to the comma or end of line.
  318.     */
  319.     while ((*src != COMMA) && (*src != EOL)) *dest++ = *src++ ;
  320.     /*
  321.     Tack on NULL for good measure.
  322.     */
  323.     *dest = '\0' ;
  324.     /*
  325.     If the source string is at a comma, move past it,
  326.     and return the up-dated string position.
  327.     */
  328.     if (*src == COMMA) {
  329.         *src++ ;
  330.         return (src) ;
  331.     }
  332.     /*
  333.     Otherwise we're at the end of the line.
  334.     */
  335.     return (NULL) ;
  336. }
  337. /*
  338.     str_position (s1, s2) - case insensitive search of s1 for s2.
  339.     Return an integer indicating the number of characters preceeding
  340.     the string found, or -1 if the string is not found.
  341. */
  342. int str_position(friskme, findme)
  343.  char friskme[] ;    /* string to search */
  344.  char findme[] ;    /* string to search for */
  345. {
  346.     int pos, match ;
  347.     
  348.     for (pos=0, match=0; pos<=strlen(friskme)-strlen(findme); pos++)
  349.     {
  350.         match = strnicmp(&friskme[pos], &findme[0], strlen(findme)) ;
  351.         if (match == 0) return(pos) ;
  352.     }
  353.     return(-1) ;
  354. }
  355. /*
  356.     pause() - wait for VANILLAKEY press.
  357.     Return 0 if aok, continue search.
  358.     Return -1 if abort search.
  359.     Return -2 to close window.
  360. */
  361. int pause()
  362. {
  363.     ULONG class ;
  364.     USHORT code ;
  365.     
  366.     Wait(1 << window->UserPort->mp_SigBit) ;
  367.     while ((message = (struct IntuiMessage *)GetMsg(window->UserPort)) != NULL) {
  368.         class = message->Class ;
  369.         code = message->Code ;
  370.         ReplyMsg((struct Message *)message) ;
  371.     }
  372.     switch (class) {
  373.         case CLOSEWINDOW:
  374.         return(-2) ;
  375.         /**/
  376.         case VANILLAKEY:
  377.         if (code == ESCKEY) return(-1) ;
  378.         return(0) ;
  379.         /**/
  380.         default:
  381.         return(-1) ;
  382.     }
  383. }
  384. /*
  385.     END OF CODE FOR SEARCHING DATABASE    */
  386. /* ************************************ */
  387. void open_all()
  388. {
  389.     if (!(IntuitionBase = OpenLibrary("intuition.library",0))) {
  390.         close_all(10) ;
  391.     }
  392.     if (!(GfxBase = OpenLibrary("graphics.library", 0))) {
  393.         close_all(20) ;
  394.     }
  395.     if (!(window = OpenWindow(&NewWindowStructure1))) {
  396.         close_all(30) ;
  397.     }
  398.     SetMenuStrip(window, &Menu1) ;
  399.     SetWindowTitles(window, msg_Intro, NULL) ;
  400.     return ;
  401. }
  402. void close_all(int status)
  403. {
  404.     if (window) ClearMenuStrip(window) ;
  405.     if (window) CloseWindow(window) ;
  406.     if (GfxBase) CloseLibrary(GfxBase) ;
  407.     if (IntuitionBase) CloseLibrary(IntuitionBase) ;
  408.     _exit(status) ;
  409. }
  410.